using System;
using System.Linq;
using System.Xml.Linq;
using Coderoom.ScrumPlanner.Data.Contracts;
using Coderoom.ScrumPlanner.Domain;
using Coderoom.ScrumPlanner.Utilities;

namespace Coderoom.ScrumPlanner.Data.Repositories.Xml
{
	public sealed class XmlProjectRepository : XmlRepository, IProjectRepository
	{
		public override string DataFileName
		{
			get { return "Projects.xml"; }
		}

		#region IProjectRepository Members

		public ProjectCollection GetProjects()
		{
			Lock.EnterReadLock();

			try
			{
				var projectData = ReadXml();

				var result = (from project in projectData.ImmediateDescendants("Project")
				              select new Project {Id = XmlExtensions.ReadAttributeAsGuid(project, "id"), Title = XmlExtensions.ReadChildValue(project, "Title"), Slug = XmlExtensions.ReadChildValue(project, "Slug")});

				return new ProjectCollection(result);
			}
			finally
			{
				Lock.ExitReadLock();
			}
		}

		public Project GetProject(Guid projectId)
		{
			Lock.EnterReadLock();

			try
			{
				return GetProjects().Where(project => project.Id == projectId).SingleOrDefault();
			}
			finally
			{
				Lock.ExitReadLock();
			}
		}

		public Project GetProject(string slug)
		{
			Lock.EnterReadLock();

			try
			{
				return GetProjects().Where(project => project.Slug == slug).SingleOrDefault();
			}
			finally
			{
				Lock.ExitReadLock();
			}
		}

		public void CreateProject(Project project)
		{
			Lock.EnterWriteLock();

			try
			{
				project.Id = Guid.NewGuid();

				var projectData = ReadXml();
				// ReSharper disable PossibleNullReferenceException
				projectData.Root.Add(new XElement("Project", new XAttribute("id", project.Id), new XElement("Title", project.Title), new XElement("Slug", project.Slug)));
				// ReSharper restore PossibleNullReferenceException
				WriteXml(projectData);
			}
			finally
			{
				Lock.ExitWriteLock();
			}
		}

		public bool DeleteProject(Guid projectId)
		{
			Lock.EnterWriteLock();

			try
			{
				var projectData = ReadXml();

				var projectToDelete = projectData.ImmediateDescendants("Project").Where(project => project.ReadAttributeAsGuid("id") == projectId).SingleOrDefault();

				if (projectToDelete != null)
				{
					projectToDelete.Remove(); // removes it from parent
					WriteXml(projectData);
					return true;
				}

				return false;
			}
			finally
			{
				Lock.ExitWriteLock();
			}
		}

		public bool DeleteProject(string slug)
		{
			Lock.EnterWriteLock();

			try
			{
				var projectData = ReadXml();

				var projectToDelete = projectData.ImmediateDescendants("Project").Where(project => project.ReadAttribute("slug") == slug).SingleOrDefault();

				if (projectToDelete != null)
				{
					projectToDelete.Remove(); // removes it from parent
					WriteXml(projectData);
					return true;
				}

				return false;
			}
			finally
			{
				Lock.ExitWriteLock();
			}
		}

		#endregion
	}
}